<?php
/**
 * Datenbankconnector
 *
 * @author		Joachim Ruf
 * @copyright	Copyright (c) 2003-2013 Loresoft Software (http://www.loresoft.de)
 * @license		http://yapary.loresoft.de/lizenzbedingungen     New BSD License
 *
 * */


class Yapary_Db_Sql_Connector
{
    private $serverName		= NULL;
    private $databaseName	= NULL;
    private $userName		= NULL;
    private $userPassword	= NULL;

    private $isConnected	= false;
    /* @var $connection MySQLi */
    private $connection		= NULL;
    private $exception		= NULL;
    private $lastQuery		= '';
	private $charset		= NULL;

    private	$triggerError	= true;


    function __construct ($_serverName, $_databaseName, $_userName, $_userPassword, $_charset = NULL) {
		$this->serverName   = $_serverName;
		$this->databaseName = $_databaseName;
		$this->userName     = $_userName;
		$this->userPassword = $_userPassword;

		$this->charset		= $_charset;
    }




    /**
     * Liefert die MYSQL-Connect
     * @return MYSQL_Connect
     * */
    public function getSqlConnect () {
        return $this->connection;
    }


    function __destruct () {
    	try {
    		if ($this->isConnected === true) {
    			@$this->connection->close();
    		}
    	} catch (Exception $e) {
    		throw new Exception('Error while disconnecting database '.mysql_errno());
    	}
    }


    public function triggerError ($_enable = true) {
    	if (!is_bool($_enable)) {
    		return false;
    	}

    	$this->triggerError	= $_enable;
    	return true;
    }


    /**
     * Stellt die Verbindung zur entspr. Datenbanktabelle her
     * @return void
     * */
    public function connect () {
    	try {
			if ($this->connection = new MySQLi(SERVER, DB_USER, DB_PASSWORD, DB_NAME)) {
				if ($this->selectDb()) {
					if ($this->charset !== NULL) {
						return $this->connection->set_charset($this->charset);
					}

					return true;
				}
			}
    	} catch (Exception $e) {
    		throw new Exception('Error while connecting to database '.mysql_errno());
    	}

    	return false;
    }


	/**
	 * Stellt die Verbindung zur entspr. Datenbanktabelle her
	 * @return void
	 * */
	private function selectDb () {
		try {
			return $this->connection->select_db($this->databaseName);
		} catch (Exception $e) {
    		throw new Exception('Error while selecting database table '.mysql_errno());
		}

		return false;
	}


	/**
	 * Erstellt eine SQL-Anfrage, bei welcher die Variablen extra uebergeben werden (koennen)
	 * (fuer Query doppelte Anfuehrungszeichen benutzen!)
	 * und gegen SQL-Injection abgesichert werden
	 * @param string $_strQuery : SQL-Query
	 * @param array $arrVar  : Array aller Parameter welche ausgetauscht werden sollen im Format :variable:
     * @return Yapary_Db_IResult|NULL
	 * */
	public function request ($_strQuery, $_arrVar = array()) {
		if ($this->isConnected === false) { // Connect on demand
			$this->connect();
			$this->isConnected = true;
		}

		if (count($_arrVar) >= 1) {
			while (list($key,$val) = each($_arrVar)) {
				if (strpos($_strQuery, ":$key") !== false) {
					if ($val !== 'NULL') {
						$_strQuery = str_replace(':'.$key, "'".$this->connection->real_escape_string($val)."'", $_strQuery); // @TODO Variablen muessen unterschiedlich benannt sein
					} else {
						$_strQuery = str_replace(':'.$key, 'NULL', $_strQuery); // @TODO Variablen muessen unterschiedlich benannt sein
					}
				}
			}
		}

		return $this->query($_strQuery);
    }


    /**
	 * Erstellt eine SQL-Anfrage (fuer Query doppelte Anfuehrungszeichen benutzen!)
     * Nur verwenden, falls die uebergebenen Variablen sicher sind.
     * Ansonsten request() verwenden um Variablen abzusichern
     * @param string $_strQuery : SQL-Query-String
     * @return Yapary_Db_IResult|NULL
     * */
    private function query ($_strQuery) {
        $this->lastQuery = $_strQuery;

		$resId		= @$this->connection->query($_strQuery);
		$errCode	= $this->connection->errno;
		$errMsg		= $this->connection->error;

		if ($errCode != 0) {
			$arrError = array();
			$arrError['message']	= 'Database query not possible';
			$arrError['errno']		= $errCode;
			$arrError['error']		= $errMsg;
			$arrError['query']		= str_replace('	', '', $_strQuery);
//			$e = new Exception();
//			$arrError['exception'] = $e->getTraceAsString();

			if ($this->triggerError) {
				trigger_error('<pre>'.print_r($arrError, true).'</pre>', E_USER_WARNING);
			}
            //return NULL;
		} else if (gettype($resId) !== 'resource' && $resId == false) {
		    //return NULL;
			throw new Exception('Database query result is not a resource: '.'('.$errCode.') '.$errMsg);
		}

		return new Yapary_Db_Sql_Result($this->connection, $resId, $_strQuery, array('errCode' => $errCode, 'errMsg' => $errMsg));
    }


    /**
     * Gibt eine Instanz der Transaction-Klasse aus
     * @return Yapary_Db_ITransaction
     * */
    public function transaction () {
    	if ($this->isConnected === false) { // Connect on demand
    		$this->connect();
    		$this->isConnected = true;
    	}

        return new Yapary_Db_Sql_Transaction($this->connection);
    }


    /**
     * Gibt eine Instanz der Datenbank-Klasse aus
     * @return Yapary_Db_IDatabase
     * */
    public function database () {
    	if ($this->isConnected === false) { // Connect on demand
    		$this->connect();
    		$this->isConnected = true;
    	}

    	return new Yapary_Db_Sql_Database($this->connection);
    }


    /**
     * Liefert alle Tabellennamen aus
     * @return string
     * */
    public function getLastQuery () {
    	if ($this->isConnected === false) { // Connect on demand
    		$this->connect();
    		$this->isConnected = true;
    	}

    	return $this->lastQuery;
    }


    public function getRealEscapeString ($_string) {
		if ($this->isConnected === false) { // Connect on demand
    		$this->connect();
    		$this->isConnected = true;
    	}

    	return $this->connection->real_escape_string($_string);
    }

}


?>